package com.partybuilding.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.partybuilding.domain.ResponseResult;
import com.partybuilding.domain.entity.*;
import com.partybuilding.domain.vo.AdmintableVo;
import com.partybuilding.domain.vo.UserInfoVo;
import com.partybuilding.enums.AppHttpCodeEnum;
import com.partybuilding.expection.SystemException;
import com.partybuilding.mapper.AdmintableMapper;
import com.partybuilding.service.AdminRoleService;
import com.partybuilding.service.AdmintableService;
import com.partybuilding.service.RoletableService;
import com.partybuilding.utils.BeanCopyUtils;
import com.partybuilding.utils.JwtUtil;
import com.partybuilding.utils.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import sun.security.util.Password;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 管理权限信息表(Admintable)表服务实现类
 *
 * @author makejava
 * @since 2023-11-03 00:46:58
 */
@Service("admintableService")
public class AdmintableServiceImpl extends ServiceImpl<AdmintableMapper, Admintable> implements AdmintableService {

    @Autowired
    private AuthenticationManager authenticationManager ;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AdminRoleService adminRoleService;

    @Autowired
    private RoletableService roletableService;

    @Autowired
    private RedisCache redisCache;
    @Override
    public ResponseResult login(Admintable admintable) {
        UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(admintable.getUser_name(),admintable.getUser_password());
        //使用authenticationManager进行认证，会调用默认UserDetailsService，所以需要重写对应实现类
        //查询用户信息结束后传入authenticate
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if(Objects.isNull(authenticate)){
            throw new RuntimeException("用户名或密码错误");
        }

        //根据内容修改已经用户登录信息，主要目的是添加用户权限范围和用户权限
//        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        //获取到已经登录的loginUser
        LoginUser loginUser=(LoginUser)authenticate.getPrincipal();
        //查询用户角色权限范围表,根据用户id返回其所有范围下对应的权限信息
        List<AdminRole> list=adminRoleService.getRolesById(admintable.getUser_id());

        //默认根据第一个角色进行页面权限展示,可以通过切换角色来实现不同权限范围的实现
        //查询角色权限表,根据角色id,返回角色信息
        Roletable role = roletableService.getRoleById(list.get(0).getRole_id());

        //将角色权限封装为list，在数据库中通过":"来分割
//        List<String> list=new ArrayList<>(Arrays.asList(role.getRoleKey().split(":")));
        List<String> listpermissions=new ArrayList<>(Arrays.asList(role.getRole_permission_id()));
        //将封装权限信息和角色id的内容传入已经登录的用户信息中即可
        loginUser.setPermissions(listpermissions);
        loginUser.setRoleId(String.valueOf(role.getRole_id()));
//        LoginUser loginUser1=new LoginUser(loginUser.getAdmintable(),list,role.getId());
//        authenticate.getPrincipal()
        SecurityContextHolder.getContext().setAuthentication(authenticate);


        //获取userid 生成token
        String adminId=loginUser.getAdmintable().getId().toString();
        String jwt = JwtUtil.createJWT(adminId);//生成jwt的工具类
        //把用户信息传入redis
        redisCache.setCacheObject("loginId:"+adminId,loginUser);
        //把token和userinfo封装 返回

        UserInfoVo userInfoVo= BeanCopyUtils.copyBean(loginUser.getAdmintable(), UserInfoVo.class);
        AdmintableVo vo=new AdmintableVo(jwt,userInfoVo);
        return ResponseResult.okResult(vo);
    }

    @Override
    public ResponseResult logout() {
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser=(LoginUser) authentication.getPrincipal();
        String userId=loginUser.getAdmintable().getUser_id();

        redisCache.deleteObject("loginId:"+userId);
        return new ResponseResult(200,"注销成功");
    }

    @Override
    public ResponseResult regist(Admintable admintable) {
        //对数据进行非空判断
       if(!StringUtils.hasText(admintable.getUser_name())){
            throw new SystemException(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        if(!StringUtils.hasText(admintable.getUser_password())){
            throw new SystemException(AppHttpCodeEnum.PASSWORD_NOT_NULL);
        }
        if(!StringUtils.hasText(admintable.getUser_id())){
            throw new SystemException(AppHttpCodeEnum.STATUS_NOT_NULL);
        }
        if(!StringUtils.hasText(admintable.getUser_nickname())){
            throw new SystemException(AppHttpCodeEnum.NICKNAME_NOT_NULL);
        }
        if(!StringUtils.hasText(admintable.getUser_branchesid())){
            throw new SystemException(AppHttpCodeEnum.AUTHORITYPARTY_NOT_NULL);
        }

        //对数据进行是否存在的判断
        if(AdminNameExist(admintable.getUser_name())){
            throw new SystemException(AppHttpCodeEnum.USERNAME_EXIST);
        }
        //对密码进行加密
        String encodePassword = passwordEncoder.encode(admintable.getUser_password());
        admintable.setUser_password(encodePassword);
        //存入数据库
        save(admintable);
        return ResponseResult.okResult( );

    }

    /**
     * @param adminName
     * 判断根据用户名判断是否存在对应用户
     * @return 返回布尔值
     */
    private boolean AdminNameExist(String adminName) {
        LambdaQueryWrapper<Admintable> admintableLambdaQueryWrapper=new LambdaQueryWrapper<>();
        admintableLambdaQueryWrapper.eq(Admintable::getUser_name,adminName);
        return (count(admintableLambdaQueryWrapper)>0?true:false);
    }
}

